﻿// ==================================================================================================
// Copyright(C) 2012 NCS Pte. Ltd. All rights reserved.
//
// SYSTEM NAME	    : iConnect .Net Application Framework
// COMPONENT ID	    : NCS.IConnect.Architecture.Client
// COMPONENT DESC   : The foundation component of the whole framework. 	
//
// CREATED DATE/BY  : 13 Apr 2012 / Wu Yong Qing
//
// REVISION HISTORY :	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================

using NCS.IConnect.Core;
using NCS.IConnect.Core.EntLib.Properties;
using NCS.IConnect.Core.IoC.TransientCall;
using System;
using System.Collections.Generic;
using System.ServiceModel;
using NCS.IConnect.Core.Utilities;

namespace NCS.IConnect.Core.IoC.TransientCall
{
    /// <summary>
    /// Channel proxy.
    /// </summary>
    public static class ChannelProxyFactory
    {
        private static readonly IDictionary<Type, bool> validationCache = new Dictionary<Type, bool>();
        private static readonly object syncObj = new object();

        private static bool IsValidServiceContract(Type type)
        {
            bool isValid;
            if (validationCache.TryGetValue(type, out isValid))
            {
                return isValid;
            }

            lock (syncObj)
            {
                if (validationCache.TryGetValue(type, out isValid))
                {
                    return isValid;
                }
                isValid = (type.IsInterface && type.GetCustomAttributes(typeof(ServiceContractAttribute), false).Length != 0);
                validationCache[type] = isValid;
                return isValid;
            }
        }

        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <param name="contractType">Type of the contract.</param>
        /// <param name="endpointName">Name of the endpoint.</param>
        /// <returns>Client proxy used to call WCF service.</returns>
        public static object GetProxy(Type contractType, string endpointName)
        {
            Guard.ArgumentNotNull(contractType, "contractType");
            Guard.ArgumentNotNullOrEmpty(endpointName, "endpointName");
            if (!IsValidServiceContract(contractType))
            {
                throw new ArgumentException(Resources.ExceptionInvalidServiceContractType.Format((object)contractType.FullName));
            }
            var channelProvider = new DefaultChannelProvider(contractType, endpointName);
            return TransientCallIntercept.GetProxy(contractType, channelProvider, new[] { new ChannelExceptionHandlingBehavior() });
        }

        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <typeparam name="T">Type of the contract.</typeparam>
        /// <param name="endpointName">Name of the endpoint.</param>
        /// <returns>Client proxy used to call WCF service.</returns>
        public static T GetProxy<T>(string endpointName) where T : class 
        {
            return (T)GetProxy(typeof(T), endpointName);
        }
    }
}